-
-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Return to using executor.wrap around Scheduler execution task #99
Conversation
Ah, hmm, perhaps the executor within activejob is checking-in the connection too early, now. Hmm. Perhaps we need to restore the executor around the perform block only, before it takes the advisory lock. I'll take a look. |
@sj26 I found something interesting/unfortunate:
For the latter issue of the query not reliably returning an advisory locked record, I can patch an additional guard clause. It's not ideal with an extra database query, but it's good until I can dig more into that. I do feel confident that returning the I'm very fascinated by all of this and appreciate your efforts 🙌 |
Sorry, I ran out of time to look at this yesterday. But I think what you're proposing here is correct. ActiveRecord installs query cache handling into the executor: It releases connections when the executor completes, regardless of whether the connection was already held before the executor starts: So by the time the ActiveJob has returned we have lost the connection which took the advisory lock. Double-wrapping the executor is harmless, the second wrap (done within ActiveJob) will simply yield: I would push the executor wrap into the perform method rather than putting it in the future for clarity about what is being wrapped a why, but this should fix the issue. 👍 This shouldn't reintroduce the deadlock because these perform methods only run for the duration of a job. The issue was the notifier being run in an executor which never returns. As long as we don't re-wrap the notifier I think we should be good. 🙌 |
@sj26 I appreciate all of your help. Especially digging into what's happening here and all the improvements 🎉
I have it in the Scheduler because it felt closer to the responsibility of the thread to set up a proper execution environment, rather than the Performer or Job-level code to be aware that it was running inside of a thread. That said, I'll admit it's perhaps un-YAGNI thinking. I think it's becoming clear that the querying/locking implementation may need to change and that might drive my thinking and and the code further. |
Nice, I tried this out locally with my async puma setup and code reload worked without deadlocks. 👍 |
This change broke my implementation in an application with I will try to also look into why the advisory lock isn't owned. Or at least will try to create an example application with same setup. |
@sj26 I'm seeing some behavior indicating that #97 is losing advisory locks. Would you be able to take a look?
It looks similar to what's described here: rails/rails#26956 (comment)
...at least, that's my hypothesis given that the Advisory Locks are connection-based, implying that the connection taking the advisory lock is a different connection than the one trying to release it (the
WARNING: you don't own a lock of type ExclusiveLock
).